package gui.productgroup;

import static org.junit.Assert.*;
import gui.common.SizeUnits;
import gui.inventory.ProductContainerData;

import org.junit.Before;
import org.junit.Test;

import persistence.DataPersistor;

import core.Container;
import core.ContainerFacade;
import core.exception.IllegalEditException;
import core.exception.NotFoundException;
import core.exception.SaveException;

public class EditProductGroupControllerTest implements IEditProductGroupView {
	private String _name;
	private String _quantity;
	private SizeUnits _unit;
	private Boolean _okEnabled;
	
	private ProductContainerData _shelf1;
	
	private EditProductGroupController _curController;

	@Before
	public void setUp() throws Exception {
		_name = "";
		_quantity = "";
		_unit = null;
		_okEnabled = true;
		
		ContainerFacade.clearAllData();
		DataPersistor.instance().init("-serial");
		
		Container basement = ContainerFacade.instance().addStorageUnit("Basement");
		Container shelf1 = ContainerFacade.instance().addProductGroup(
				basement, "shelf1", "0", "count");
		ContainerFacade.instance().addProductGroup(
				basement, "shelf2", "4.32", "fluid ounces");
		ContainerFacade.instance().addProductGroup(
				shelf1, "bucket", "888", "gallons");
		
		_shelf1 = new ProductContainerData(shelf1);

		_curController = null;
	}

	@Test
	public void testLoadValues() {
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("0.0",_quantity);
		assertEquals(SizeUnits.Count, _unit);
		
		changeInfo(_shelf1,"shelf1","1.3","gallons");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Gallons, _unit);		
		
		changeInfo(_shelf1,"shelf1","1.3","grams");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Grams, _unit);
		
		changeInfo(_shelf1,"shelf1","1.3","fluid ounces");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.FluidOunces, _unit);	
		
		changeInfo(_shelf1,"shelf1","1.3","liters");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Liters, _unit);		
		
		changeInfo(_shelf1,"shelf1","1.3","kilograms");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Kilograms, _unit);	
		
		changeInfo(_shelf1,"shelf1","1.3","ounces");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Ounces, _unit);	
		
		changeInfo(_shelf1,"shelf1","1.3","pints");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Pints, _unit);
		
		changeInfo(_shelf1,"shelf1","1.3","pounds");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Pounds, _unit);	
		
		changeInfo(_shelf1,"shelf1","1.3","quarts");
		_curController = new EditProductGroupController(this,_shelf1);
		assertEquals("shelf1",_name);
		assertEquals("1.3",_quantity);
		assertEquals(SizeUnits.Quarts, _unit);	
	}

	@Test
	public void testEnableComponents() {
		_curController = new EditProductGroupController(this,_shelf1);
		
		_name = "shelf2";
		_okEnabled = true;
		_curController.enableComponents();
		assertFalse(_okEnabled);
		
		_name = "shelf1";
		_okEnabled = false;
		_curController.enableComponents();
		assertTrue(_okEnabled);
		
		_name = "bucket";
		_okEnabled = false;
		_curController.enableComponents();
		assertTrue(_okEnabled);
		
		_quantity = "";
		_okEnabled = true;
		_curController.enableComponents();
		assertFalse(_okEnabled);
		
		_quantity = "1.2";
		_unit = SizeUnits.Count;
		_okEnabled = true;
		_curController.enableComponents();
		assertFalse(_okEnabled);	
		
		_quantity = "-3";
		_okEnabled = true;
		_curController.enableComponents();
		assertFalse(_okEnabled);	
		
		_quantity = "abc";
		_okEnabled = true;
		_curController.enableComponents();
		assertFalse(_okEnabled);	
		
		_quantity = "1.11.11";
		_okEnabled = true;
		_curController.enableComponents();
		assertFalse(_okEnabled);	
		
		_quantity = "3.68888888888888";
		_unit = SizeUnits.FluidOunces;
		_okEnabled = false;
		_curController.enableComponents();
		assertTrue(_okEnabled);				
	}

	@Test
	public void testValuesChanged() {
		_curController = new EditProductGroupController(this,_shelf1);
		
		setProductGroupName("");
		assertFalse(_okEnabled);
		
		_okEnabled = false;
		setProductGroupName("s");
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setProductGroupName("sh");		
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setProductGroupName("she");		
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setProductGroupName("shel");
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setProductGroupName("shelf");
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setProductGroupName("shelf1");
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setProductGroupName("shelf");
		assertTrue(_okEnabled);	
		
		_okEnabled = true;
		setProductGroupName("shelf2");
		assertFalse(_okEnabled);
		
		_okEnabled = false;
		setProductGroupName("shelf2b");
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Count);
		assertTrue(_okEnabled);		
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.FluidOunces);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Gallons);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Grams);
		assertTrue(_okEnabled);		
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Kilograms);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Liters);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Ounces);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Pints);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Pounds);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Quarts);
		assertTrue(_okEnabled);	
		
		_okEnabled = false;
		setSupplyUnit(SizeUnits.Count);
		assertTrue(_okEnabled);	
		
		_okEnabled = true;
		setSupplyValue("");
		assertFalse(_okEnabled);
		
		_okEnabled = true;		
		setSupplyValue("-");
		assertFalse(_okEnabled);	

		_okEnabled = true;
		setSupplyValue("-1");
		assertFalse(_okEnabled);

		_okEnabled = true;
		setSupplyValue("1.1");
		assertFalse(_okEnabled);	
		
		_okEnabled = false;
		setSupplyValue("1.0");
		assertTrue(_okEnabled);			
		
	}

	@Test
	public void testEditProductGroup() {
		_curController = new EditProductGroupController(this,_shelf1);
		
		setProductGroupName("Bucket");
		setSupplyUnit(SizeUnits.FluidOunces);
		setSupplyValue("0.12381235");
		
		assertTrue(_okEnabled);
		_curController.editProductGroup();
		
		assertEquals("Bucket",_shelf1.getContainer().getName());
		assertEquals("fluid ounces",ContainerFacade.instance().
				get3MonthSupplyUnit(_shelf1.getContainer()));
		assertEquals("0.12381235",ContainerFacade.instance().
				get3MonthSupplyQuantity(_shelf1.getContainer()));
		
	}
	
	public void changeInfo(ProductContainerData data, String name, String value, String unit){
		try {
			ContainerFacade.instance().renameContainer(data.getContainer(), name);
			ContainerFacade.instance().setThreeMonthSupply(data.getContainer(), value, unit);
			data.setName(name);		
		} catch (IllegalEditException | NotFoundException | IllegalArgumentException | 
				SaveException e) {
			// this is unexpected!
			fail(e.getMessage());
		}
	
		
	}

	@Override
	public void displayInformationMessage(String message) {
		// not used
		
	}

	@Override
	public void displayWarningMessage(String message) {
		// not used
		
	}

	@Override
	public void displayErrorMessage(String message) {
		fail(message);
		
	}

	@Override
	public String getProductGroupName() {
		return _name;
	}

	@Override
	public void setProductGroupName(String value) {
		_name = value;
		if (_curController != null)
			_curController.valuesChanged();
		
	}

	@Override
	public void enableProductGroupName(boolean value) {
		// not used
		
	}

	@Override
	public String getSupplyValue() {
		return _quantity;
	}

	@Override
	public void setSupplyValue(String value) {
		_quantity = value;
		if (_curController != null)
			_curController.valuesChanged();
		
	}

	@Override
	public void enableSupplyValue(boolean value) {
		// not used
		
	}

	@Override
	public SizeUnits getSupplyUnit() {
		return _unit;
	}

	@Override
	public void setSupplyUnit(SizeUnits value) {
		_unit = value;
		if (_curController != null)
			_curController.valuesChanged();
		
	}

	@Override
	public void enableSupplyUnit(boolean value) {
		// not used
		
	}

	@Override
	public void enableOK(boolean value) {
		_okEnabled = value;
		
	}

}
